/*
 *  Copyright (C) 1993  Robert Davis
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of Version 2, or any later version, of 
 *  the GNU General Public License as published by the Free Software 
 *  Foundation.
 */


static char RCSId[]="$Id: StatusContour.m,v 1.10 1993/05/18 03:55:42 davis Exp $";



#import "DoubleObject.h"
#import "DoubleValueSortedList.h"
#import "StatusContour.h"

#define MAX_DISCRETE_LEVELS	30

extern int	draw_contour;
extern int	contour_kind;
extern int	contour_pts;
extern int	contour_order;
extern int	contour_levels;
extern int	levels_kind;
extern double	levels_list[MAX_DISCRETE_LEVELS];
extern int	label_contours;

@implementation Status (Contour)

- initContour
{
    levelDefs = nil;
    return self;
}


- freeContour
{
    if (levelDefs)
	[[levelDefs freeObjects] free];

    return self;
}


- resetCurrentContour
{
    contourBase = NO;
    contourSurface = NO;
    s_contour_kind = CONTOUR_KIND_LINEAR;
    s_contour_pts = 5;
    s_contour_order = 4;
    s_contour_levels = 5;
    s_levels_kind = LEVELS_AUTO;
    s_levelsSeries.start = -1.0;
    s_levelsSeries.incr = .25;
    s_levelsSeries.end = 1.0;
    s_label_contours = YES;

    if (levelDefs)
	[levelDefs freeObjects];
    else {
	levelDefs = [[DoubleValueSortedList allocFromZone:zone] init];
	[levelDefs setMax:MAX_DISCRETE_LEVELS];
    }

    return self;
}


- applyCurrentContour
{
    int i;

    if (!contourBase && !contourSurface)
	draw_contour = CONTOUR_NONE;
    else if (contourBase && contourSurface)
	draw_contour = CONTOUR_BOTH;
    else if (contourBase)
	draw_contour = CONTOUR_BASE;
    else if (contourSurface)
	draw_contour = CONTOUR_SRF;

    contour_kind = s_contour_kind;
    contour_pts = s_contour_pts;
    contour_order = s_contour_order;

    switch (levels_kind = s_levels_kind) {
    case LEVELS_INCREMENTAL:
	levels_list[0] = s_levelsSeries.start;
	levels_list[1] = s_levelsSeries.incr;
	contour_levels = (s_levelsSeries.end - s_levelsSeries.start)
			    / s_levelsSeries.incr;
	break;
    case LEVELS_DISCRETE:
	contour_levels = [levelDefs count];
	for (i = 0; i < contour_levels; i++)
	     levels_list[i] = [[levelDefs objectAt:i] doubleValue];
	break;
    default:
	contour_levels = s_contour_levels;
    }

    label_contours = s_label_contours;

    return self;
}


- grabCurrentContour
{
    int i, maxi;

    switch (draw_contour) {
    case CONTOUR_NONE:
	contourBase = contourSurface = NO;
	break;
    case CONTOUR_BASE:
	contourBase = YES;
	contourSurface = NO;
	break;
    case CONTOUR_SRF:
	contourBase = NO;
	contourSurface = YES;
	break;
    default:
	contourBase = YES;
	contourSurface = YES;
	break;
    }

    switch (s_levels_kind = levels_kind) {
    case LEVELS_INCREMENTAL:
	s_levelsSeries.start = levels_list[0];
	s_levelsSeries.incr = levels_list[1];
	s_levelsSeries.end = (contour_levels * levels_list[1]) +levels_list[0];
	s_contour_levels = contour_levels;
	break;
    case LEVELS_DISCRETE:
	maxi = [levelDefs count] - 1;
	for (i = 0; i < contour_levels; i++) {
	    if (i <= maxi)
		[[levelDefs objectAt:i] setDoubleValue:levels_list[i]];
	    else {
		DoubleObject *dobj = [[DoubleObject allocFromZone:zone]
						initFromDouble:levels_list[i]];
		if ([levelDefs addObjectIfDoubleAbsent:dobj] == NX_NOT_IN_LIST)
		    [dobj free];
	    }
	}
	s_contour_levels = [levelDefs count];
	break;
    case LEVELS_AUTO:
	s_contour_levels = contour_levels;
	break;
    }

    s_contour_pts = contour_pts;
    s_contour_order = contour_order;
    s_levels_kind = levels_kind;
    s_label_contours = label_contours;

    return self;
}



- setContourBase:(BOOL) cond
{
    if (contourBase != cond) {
	contourBase = cond;
	[self reportSettingsChange:self];
    }

    return self;
}


- (BOOL) contourBase
{
    return contourBase;
}



- setContourSurface:(BOOL) cond
{
    if (contourSurface != cond) {
	contourSurface = cond;
	[self reportSettingsChange:self];
    }

    return self;
}


- (BOOL) contourSurface
{
    return contourSurface;
}



- setContourKind:(int) anInt
{
    if (anInt != s_contour_kind) {
	s_contour_kind = anInt;
	[self reportSettingsChange:self];
    }

    return self;
}



- (int) contourKind;
{
    return s_contour_kind;
}



- setContourPoints:(int) anInt
{
    if ((anInt != s_contour_pts) && (anInt > 0)) {
	s_contour_pts = anInt;
	[self reportSettingsChange:self];
    }

    return self;
}


- (int) contourPoints
{
    return s_contour_pts;
}



- setContourOrder:(int) anInt
{
    if ((anInt != s_contour_order) && (anInt >= 2) && (anInt <= 10)) {
	s_contour_order = anInt;
	[self reportSettingsChange:self];
    }

    return self;
}


- (int) contourOrder
{
    return s_contour_order;
}


- setContourLevels:(int) anInt
{
    if (anInt != [self contourLevels] && (anInt > 0)) {
	if (s_levels_kind == LEVELS_INCREMENTAL) {
	    s_levelsSeries.end = (anInt * s_levelsSeries.incr) +
							s_levelsSeries.start;
	} else if (s_levels_kind == LEVELS_AUTO) {
	    s_contour_levels = anInt;
	}

	[self reportSettingsChange:self];
    }

    return self;
}


- (int) contourLevels
{
    switch (s_levels_kind) {
    case LEVELS_INCREMENTAL:
	return (s_levelsSeries.end -s_levelsSeries.start) /s_levelsSeries.incr;
    case LEVELS_DISCRETE:
	return [levelDefs count];
    default:
	return s_contour_levels;
    }
}


- setContourLevelsKind:(int) anInt;
{
    if (anInt != s_levels_kind) {
	s_levels_kind = anInt;
	[self reportSettingsChange:self];
    }

    return self;
}



- (int) contourLevelsKind
{
    return s_levels_kind;
}



- setContourLevelsStart:(double)aDouble
{
    if (aDouble != s_levelsSeries.start) {
	s_levelsSeries.start = aDouble;
	[self reportSettingsChange:self];
    }

    return self;
}



- (double)contourLevelsStart
{
    return s_levelsSeries.start;
}



- setContourLevelsIncr:(double)aDouble
{
    if (aDouble && (aDouble != s_levelsSeries.incr)) {
	s_levelsSeries.incr = aDouble;
	[self reportSettingsChange:self];
    }

    return self;
}



- (double)contourLevelsIncr
{
    return s_levelsSeries.incr;
}



- setContourLevelsEnd:(double)aDouble
{
    if (aDouble != s_levelsSeries.end) {
	s_levelsSeries.end = aDouble;
	[self reportSettingsChange:self];
    }

    return self;
}



- (double)contourLevelsEnd
{
    return s_levelsSeries.end;
}


- (DoubleValueSortedList *)levelDefs
{
    return levelDefs;
}



- setContourInKey:(BOOL) cond
{
    if (cond != s_label_contours) {
	s_label_contours = cond;
	[self reportSettingsChange:self];
    }

    return self;
}


- (BOOL)contourInKey
{
    return s_label_contours;
}



// Shuts up the compiler about unused RCSId
- (const char *) rcsid
{
    return RCSId;
}


@end
